Option Explicit

Private Const TEST_TABLE_NAME As String = "table1"
Private Const TEST_POINT As String = "."
Private Const TEST_COL_NAME As String = "col1"
Private Const TEST_SHARE_LINE_COMMENT As String = "--aaaaaa"
Private Const TEST_SINGLE_LINE_COMMENT As String = "--bbbbb"

' ======================================================================
' 执行所有测试用例
' ======================================================================
Public Sub test_all_case()
    ' ==================================================
    ' Public 方法测试
    ' ==================================================
    ' 测试: Init 方法
    test_ThisClass_Init

    ' ==================================================
    ' ISqlFormatterElem 接口实现测试
    ' ==================================================
    ' 测试: addComponent 方法
    test_ISqlFormatterElem_addComponent
    ' 测试: addComponentToFirst 方法
    test_ISqlFormatterElem_addComponentToFirst
    ' 测试: canAddComponentToFirst 方法
    test_ISqlFormatterElem_canAddComponentToFirst
    ' 测试: getAlignmentElemGroups 方法
    test_ISqlFormatterElem_getAlignmentElemGroups
    ' 测试: setElemNestCount 方法
    test_ISqlFormatterElem_setElemNestCount
    ' 测试: setPrefixSpaceCount 方法
    test_ISqlFormatterElem_setPrefixSpaceCount
    ' 测试: hasBoundaryParenthesis 方法
    test_ISqlFormatterElem_hasBoundaryParenthesis
    ' 测试: addBoundaryLeftParenthesis 方法
    test_ISqlFormatterElem_addBoundaryLeftParenthesis
    ' 测试: addBoundaryRightParenthesis 方法
    test_ISqlFormatterElem_addBoundaryRightParenthesis
    ' 测试: getType 方法
    test_ISqlFormatterElem_getType
    ' 测试: isComment 方法
    test_ISqlFormatterElem_isComment
    ' 测试: isShareLineComment 方法
    test_ISqlFormatterElem_isShareLineComment
    ' 测试: isSingleLineComment 方法
    test_ISqlFormatterElem_isSingleLineComment
    ' 测试: isEndsWithComment 方法
    test_ISqlFormatterElem_isEndsWithComment
    ' 测试: isMultiLine 方法
    test_ISqlFormatterElem_isMultiLine
    ' 测试: toString + toStringArray 方法
    test_ISqlFormatterElem_toString_toStringArray
End Sub


' ======================================================================
' 测试通用处理
' ======================================================================

' case 运算符
Private Function getCaseToken() As SqlToken
    Set getCaseToken = New SqlToken
    getCaseToken.Init "case", SqlTokenType.KEY_CASE
End Function

' case 的 when 运算符
Private Function getWhenToken() As SqlToken
    Set getWhenToken = New SqlToken
    getWhenToken.Init "when", SqlTokenType.KEY_WHEN
End Function

' case 的 else 运算符
Private Function getElseToken() As SqlToken
    Set getElseToken = New SqlToken
    getElseToken.Init "else", SqlTokenType.KEY_ELSE
End Function

' case 的 Then 运算符
Private Function getThenToken() As SqlToken
    Set getThenToken = New SqlToken
    getThenToken.Init "then", SqlTokenType.KEY_THEN
End Function

' case 的 End 运算符
Private Function getEndToken() As SqlToken
    Set getEndToken = New SqlToken
    getEndToken.Init "end", SqlTokenType.KEY_END
End Function

' 获取逻辑运算符: and
Private Function getAndToken() As SqlToken
    Set getAndToken = New SqlToken
    getAndToken.Init "and", SqlTokenType.KEY_AND
End Function

' 获取一个条件运算符: <=
Private Function getLeConditionOperator() As SqlToken
    Set getLeConditionOperator = New SqlToken
    getLeConditionOperator.Init "<=", SqlTokenType.OPERA_LE
End Function

' 获取一个任意名称的 STR_NAME token
Private Function getStrNameToken(ByRef s As String) As SqlToken
    Set getStrNameToken = New SqlToken
    getStrNameToken.Init s, SqlTokenType.STR_NAME
End Function

' 获取表名 token
Private Function getTableNameToken() As SqlToken
    Set getTableNameToken = New SqlToken
    getTableNameToken.Init TEST_TABLE_NAME, SqlTokenType.STR_NAME
End Function

' 获取 [.] token
Private Function getPointToken() As SqlToken
    Set getPointToken = New SqlToken
    getPointToken.Init TEST_POINT, SqlTokenType.POINT
End Function

' 获取列名 token
Private Function getColNameToken() As SqlToken
    Set getColNameToken = New SqlToken
    getColNameToken.Init TEST_COL_NAME, SqlTokenType.STR_NAME
End Function

' 获取和前一个元素在同一行的注释
Private Function getShareLineCommentToken() As SqlToken
    Set getShareLineCommentToken = New SqlToken
    getShareLineCommentToken.Init TEST_SHARE_LINE_COMMENT, SqlTokenType.SHARE_LINE_COMMENT
End Function

' 获取一个单行的注释
Private Function getSingleLineCommentToken() As SqlToken
    Set getSingleLineCommentToken = New SqlToken
    getSingleLineCommentToken.Init TEST_SINGLE_LINE_COMMENT, SqlTokenType.SINGLE_LINE_COMMENT
End Function

' 获取一个逗号的元素
Private Function getCommaToken() As SqlToken
    Set getCommaToken = New SqlToken
    getCommaToken.Init ",", SqlTokenType.COMMA
End Function

' 单行的 when 表达式
' when x1 then x2
Private Function getWhenExpr() As ISqlFormatterElem
    Dim result As SqlFormatterCaseCompositionElem
    Set result = New SqlFormatterCaseCompositionElem
    result.Init getWhenToken

    result.ISqlFormatterElem_addComponent getStrNameToken("x1")
    result.ISqlFormatterElem_addComponent getThenToken
    result.ISqlFormatterElem_addComponent getStrNameToken("x2")

    Set getWhenExpr = result
End Function

' 多行的 when 表达式
' when
'     x1
'     then
'     col1,
'     col2
Private Function getMultiLineWhenExpr() As ISqlFormatterElem
    Dim result As SqlFormatterCaseCompositionElem
    Set result = New SqlFormatterCaseCompositionElem
    result.Init getWhenToken

    result.ISqlFormatterElem_addComponent getStrNameToken("x1")
    result.ISqlFormatterElem_addComponent getThenToken
    result.ISqlFormatterElem_addComponent getMultiLineElemNoParenthesis

    Set getMultiLineWhenExpr = result
End Function

' 单行的 else 表达式
' else x1
Private Function getElseExpr() As ISqlFormatterElem
    Dim result As SqlFormatterCaseCompositionElem
    Set result = New SqlFormatterCaseCompositionElem
    result.Init getElseToken

    result.ISqlFormatterElem_addComponent getStrNameToken("x1")

    Set getElseExpr = result
End Function

' 将一个元素包装成 when 表达式
' when 任意内容 then x1
Private Function wrapToWhenExpr(ByRef e As ISqlFormatterElem) As ISqlFormatterElem

    Dim result As SqlFormatterCaseCompositionElem
    Set result = New SqlFormatterCaseCompositionElem
    result.Init getWhenToken

    result.ISqlFormatterElem_addComponent e
    result.ISqlFormatterElem_addComponent getThenToken
    result.ISqlFormatterElem_addComponent getStrNameToken("x1")

    Set wrapToWhenExpr = result
End Function

' 将一个元素包装成多行的 when 表达式
' when
'     任意内容
'     then
'     col1,
'     col2
Private Function wrapToMultiWhenExpr(ByRef e As ISqlFormatterElem) As ISqlFormatterElem

    Dim result As SqlFormatterCaseCompositionElem
    Set result = New SqlFormatterCaseCompositionElem
    result.Init getWhenToken

    result.ISqlFormatterElem_addComponent e
    result.ISqlFormatterElem_addComponent getThenToken
    result.ISqlFormatterElem_addComponent getMultiLineElemNoParenthesis

    Set wrapToMultiWhenExpr = result
End Function


' 获取一个没有边界括号的多行元素
' 多行连接的结果:
' col1,
' col2
Private Function getMultiLineElemNoParenthesis() As ISqlFormatterElem
    Dim g As SqlFormatterCommaDeliMultiElem
    Set g = New SqlFormatterCommaDeliMultiElem

    Dim elem As ISqlFormatterElem
    Set elem = g

    ' 1. 增加一个单行元素
    elem.addComponent getStrNameToken("col1")

    ' 2. 手动设置为多行元素，仍然是单行
    g.setNeedMultiLineWhenHasComma True

    ' 3. 在末尾添加一个逗号元素，仍然是单行的
    elem.addComponent getCommaToken

    ' 4. 再增加一个单行元素，变成多行的
    elem.addComponent getStrNameToken("col2")

    Set getMultiLineElemNoParenthesis = elem
End Function

' 获取一个没有边界括号的多行元素
' 多行连接的结果:
' col1 & ","
' col2 --aaaaaa
Private Function getMultiLineElemNoParenthesisEndWithComment() As ISqlFormatterElem
    Dim g As SqlFormatterCommaDeliMultiElem
    Set g = New SqlFormatterCommaDeliMultiElem

    Dim elem As ISqlFormatterElem
    Set elem = g

    ' 1. 增加一个单行元素
    elem.addComponent getStrNameToken("col1")

    ' 2. 手动设置为多行元素，仍然是单行
    g.setNeedMultiLineWhenHasComma True

    ' 3. 在末尾添加一个逗号元素，仍然是单行的
    elem.addComponent getCommaToken

    ' 4. 再增加一个单行元素，变成多行的
    elem.addComponent getStrNameToken("col2")

    ' 5. 增加一个和前一个元素同一行的注释
    elem.addComponent getShareLineCommentToken

    Set getMultiLineElemNoParenthesisEndWithComment = elem
End Function

' 获取一个单行的函数体
' 连接的结果:
' (col1, col2)
Private Function getSingleLineFuncBody() As ISqlFormatterElem
    Dim g As SqlFormatterCommaDeliMultiElem
    Set g = New SqlFormatterCommaDeliMultiElem

    Dim elem As ISqlFormatterElem
    Set elem = g

    ' 1. 增加一个单行元素
    elem.addComponent getStrNameToken("col1")


    ' 3. 在末尾添加一个逗号元素，仍然是单行的
    elem.addComponent getCommaToken

    ' 4. 再增加一个单行元素，变成多行的
    elem.addComponent getStrNameToken("col2")

    ' 5. 设置边界括号
    elem.addBoundaryLeftParenthesis
    elem.addBoundaryRightParenthesis

    Set getSingleLineFuncBody = elem
End Function

' 获取一个多行的函数体
' 连接的结果:
' (
'     col1,
'     col2
' )
Private Function getMultiLineFuncBody() As ISqlFormatterElem
    Dim g As SqlFormatterCommaDeliMultiElem
    Set g = New SqlFormatterCommaDeliMultiElem

    Dim elem As ISqlFormatterElem
    Set elem = g

    ' 1. 增加一个单行元素
    elem.addComponent getStrNameToken("col1")

    ' 2. 手动设置为多行元素，仍然是单行
    g.setNeedMultiLineWhenHasComma True

    ' 3. 在末尾添加一个逗号元素，仍然是单行的
    elem.addComponent getCommaToken

    ' 4. 再增加一个单行元素，变成多行的
    elem.addComponent getStrNameToken("col2")

    ' 5. 设置边界括号
    elem.addBoundaryLeftParenthesis
    elem.addBoundaryRightParenthesis

    Set getMultiLineFuncBody = elem
End Function


' ======================================================================
' Public 方法测试
' ======================================================================
' 测试: Init 方法
Private Sub test_ThisClass_Init()
    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim config As SqlFormatterConfiguration
    Set config = New SqlFormatterConfiguration

    Dim g As SqlFormatterCaseCol

    ' ==============================
    ' 2. 测试
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken
    Debug.Assert g.ISqlFormatterElem_toString(config) = "case"

End Sub

' ======================================================================
' ISqlFormatterElem 接口实现测试
' ======================================================================
' 测试: addComponent 方法
Private Sub test_ISqlFormatterElem_addComponent()
    Dim config As SqlFormatterConfiguration
    Set config = New SqlFormatterConfiguration

    Dim strArr As IPrimitiveArrayRef

    Dim g As SqlFormatterCaseCol

    ' ==============================
    ' 1. 增加一个 when 表达式
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 1. 不添加任何元素，并检查
    ' 检查: 是单行的
    Debug.Assert g.ISqlFormatterElem_isMultiLine = False
    ' 检查: 不是注释结尾
    Debug.Assert g.ISqlFormatterElem_isEndsWithComment = False

    ' 2. 增加一个 when 表达式
    g.ISqlFormatterElem_addComponent getWhenExpr

    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 2
    Debug.Assert strArr.Item(0) = "case"
    Debug.Assert strArr.Item(1) = "    when x1 then x2"

    ' 检查: 是多行的
    Debug.Assert g.ISqlFormatterElem_isMultiLine = True
    ' 检查: 不是注释结尾
    Debug.Assert g.ISqlFormatterElem_isEndsWithComment = False

    ' 3. 添加end
    g.ISqlFormatterElem_addComponent getEndToken
    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 3
    Debug.Assert strArr.Item(0) = "case"
    Debug.Assert strArr.Item(1) = "    when x1 then x2"
    Debug.Assert strArr.Item(2) = "end"

    ' 检查: 是多行的
    Debug.Assert g.ISqlFormatterElem_isMultiLine = True
    ' 检查: 不是注释结尾
    Debug.Assert g.ISqlFormatterElem_isEndsWithComment = False

    ' 4. 添加一个和前一个元素同一行的注释
    g.ISqlFormatterElem_addComponent getShareLineCommentToken

    ' 检查是多行的
    Debug.Assert g.ISqlFormatterElem_isMultiLine = True
    ' 检查: 是注释结尾
    Debug.Assert g.ISqlFormatterElem_isEndsWithComment = True

    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 3
    Debug.Assert strArr.Item(0) = "case"
    Debug.Assert strArr.Item(1) = "    when x1 then x2"
    Debug.Assert strArr.Item(2) = "end " & TEST_SHARE_LINE_COMMENT

    ' 5. 在 End 后面再增加一个元素
    g.ISqlFormatterElem_addComponent getStrNameToken("y1")

    ' 检查是多行的
    Debug.Assert g.ISqlFormatterElem_isMultiLine = True
    ' 检查: 不是注释结尾
    Debug.Assert g.ISqlFormatterElem_isEndsWithComment = False

    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 4
    Debug.Assert strArr.Item(0) = "case"
    Debug.Assert strArr.Item(1) = "    when x1 then x2"
    Debug.Assert strArr.Item(2) = "end " & TEST_SHARE_LINE_COMMENT
    Debug.Assert strArr.Item(3) = "y1"

    ' ==============================
    ' 2. 添加一个多行的 when、一个单行的 when、一个单行的 else
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken
    ' 1. 添加第一个多行 when
    g.ISqlFormatterElem_addComponent getMultiLineWhenExpr
    ' 2. 添加第一个单行 when
    g.ISqlFormatterElem_addComponent getWhenExpr
    ' 3. 添加第一个单行 else
    g.ISqlFormatterElem_addComponent getElseExpr
    ' 4. 添加 end
    g.ISqlFormatterElem_addComponent getEndToken

    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 9
    Debug.Assert strArr.Item(0) = "case"
    Debug.Assert strArr.Item(1) = "    when"
    Debug.Assert strArr.Item(2) = "        x1"
    Debug.Assert strArr.Item(3) = "        then"
    Debug.Assert strArr.Item(4) = "        col1,"
    Debug.Assert strArr.Item(5) = "        col2"
    Debug.Assert strArr.Item(6) = "    when x1 then x2"
    Debug.Assert strArr.Item(7) = "    else x1"
    Debug.Assert strArr.Item(8) = "end"

    ' 检查是多行的
    Debug.Assert g.ISqlFormatterElem_isMultiLine = True
    ' 检查: 不是注释结尾
    Debug.Assert g.ISqlFormatterElem_isEndsWithComment = False

End Sub

' 测试: addComponentToFirst 方法
Private Sub test_ISqlFormatterElem_addComponentToFirst()
    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim config As SqlFormatterConfiguration
    Set config = New SqlFormatterConfiguration

    Dim g As SqlFormatterCaseCol
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' ==============================
    ' 2. 从左侧添加元素无效
    ' ==============================
    g.ISqlFormatterElem_addComponentToFirst getStrNameToken("c1")

    Debug.Assert g.ISqlFormatterElem_toString(config) = "case"
End Sub

' 测试: canAddComponentToFirst 方法
Private Sub test_ISqlFormatterElem_canAddComponentToFirst()
    Dim g As SqlFormatterCaseCol
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 1. 默认为 False
    Debug.Assert g.ISqlFormatterElem_canAddComponentToFirst = False
End Sub

' 测试: getAlignmentElemGroups 方法
Private Sub test_ISqlFormatterElem_getAlignmentElemGroups()
    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim g As SqlFormatterCaseCol
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    Dim condition As SqlFormatterTwoElemCondition
    Dim condition2 As SqlFormatterTwoElemCondition

    Dim when As ISqlFormatterElem
    Dim elem As ISqlFormatterElem
    Set elem = g

    Dim groups As IObjArrayRef
    Dim group As IObjArrayRef

    ' ==============================
    ' 2. 在添加元素之前进行检查
    ' ==============================
    Debug.Assert elem.getAlignmentElemGroups Is Nothing

    ' ==============================
    ' 3. 添加第一个单行元素后再检查
    ' ==============================
    elem.addComponent getTableNameToken
    Debug.Assert elem.getAlignmentElemGroups Is Nothing

    ' ==============================
    ' 4. 添加第一个条件对象(包装成 when)
    ' ==============================
    Set condition = New SqlFormatterTwoElemCondition
    Set when = wrapToWhenExpr(condition)
    elem.addComponent when

    Set groups = elem.getAlignmentElemGroups
    Debug.Assert groups.Count = 1
    Set group = groups.Item(0)
    Debug.Assert group.Count = 1
    Debug.Assert group.Item(0) Is condition

    ' ==============================
    ' 5. 添加第二个条件对象(包装成 when)
    ' ==============================
    Set condition2 = New SqlFormatterTwoElemCondition
    Set when = wrapToWhenExpr(condition2)
    elem.addComponent when

    Set groups = elem.getAlignmentElemGroups
    Debug.Assert groups.Count = 2
    ' 检查第一个条件
    Set group = groups.Item(0)
    Debug.Assert group.Count = 1
    Debug.Assert group.Item(0) Is condition
    ' 检查第二个条件
    Set group = groups.Item(1)
    Debug.Assert group.Count = 1
    Debug.Assert group.Item(0) Is condition2

    ' ==============================
    ' 6. 添加一个包含多个条件对象的组合对象(包装成 when)
    ' ==============================
    ' 创建一个包含多个条件的组合对象
    Dim multiConditions As SqlFormatterCommaDeliMultiElem
    Set multiConditions = New SqlFormatterCommaDeliMultiElem
    Dim condition3 As SqlFormatterTwoElemCondition
    Set condition3 = New SqlFormatterTwoElemCondition
    Dim condition4 As SqlFormatterTwoElemCondition
    Set condition4 = New SqlFormatterTwoElemCondition
    multiConditions.ISqlFormatterElem_addComponent condition3
    multiConditions.ISqlFormatterElem_addComponent condition4

    ' 将这个组合对象保存到 elem (包装成 when)
    Set when = wrapToWhenExpr(multiConditions)
    elem.addComponent when

    Set groups = elem.getAlignmentElemGroups
    Debug.Assert groups.Count = 4
    ' 检查第一个条件
    Set group = groups.Item(0)
    Debug.Assert group.Count = 1
    Debug.Assert group.Item(0) Is condition
    ' 检查第二个条件
    Set group = groups.Item(1)
    Debug.Assert group.Count = 1
    Debug.Assert group.Item(0) Is condition2
    ' 检查第三个条件
    Set group = groups.Item(2)
    Debug.Assert group.Count = 1
    Debug.Assert group.Item(0) Is condition3
    ' 检查第四个条件
    Set group = groups.Item(3)
    Debug.Assert group.Count = 1
    Debug.Assert group.Item(0) Is condition4

End Sub

' 测试: setElemNestCount 方法
Private Sub test_ISqlFormatterElem_setElemNestCount()
    ' 这里使用一个条件对象作为函数体，并通过对齐长度来检查

    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim config As SqlFormatterConfiguration
    Set config = New SqlFormatterConfiguration

    Dim g As SqlFormatterCaseCol

    Dim condition As SqlFormatterTwoElemCondition

    Dim when As ISqlFormatterElem

    ' ==============================
    ' 1. 测试: 增加一个单行的条件元素
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 1. 创建一个条件对象
    Set condition = New SqlFormatterTwoElemCondition
    ' 设置 and
    condition.ISqlFormatterCondition_setLogicOperator getAndToken
    ' 设置第一个元素
    condition.ISqlFormatterElem_addComponent getStrNameToken("x1")
    ' 设置条件运算符 <=
    condition.ISqlFormatterCondition_setConditionOperator getLeConditionOperator
    ' 设置第二个元素
    condition.ISqlFormatterElem_addComponent getStrNameToken("x2")

    ' 2. 添加这个条件对象
    Set when = wrapToWhenExpr(condition)
    g.ISqlFormatterElem_addComponent when

    ' 3. 设置嵌套深度
    g.ISqlFormatterElem_setElemNestCount 2, config

    ' 4. 检查条件对象的对齐长度
    ' and x1 <= x2
    ' 123456789
    ' 8 + 9 + 4(在 case 下的换行产生的前缀空格) + 5(when/else 字符长度 + 1 个分隔元素的空格)
    Debug.Assert condition.ISqlFormatterAlignmentElem_getAlignmentSize(config) = 26

    ' ==============================
    ' 2. 测试: 增加一个单行条件 + 多行元素
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 1. 创建一个条件对象
    Set condition = New SqlFormatterTwoElemCondition
    ' 设置 and
    condition.ISqlFormatterCondition_setLogicOperator getAndToken
    ' 设置第一个元素
    condition.ISqlFormatterElem_addComponent getStrNameToken("x1")
    ' 设置条件运算符 <=
    condition.ISqlFormatterCondition_setConditionOperator getLeConditionOperator
    ' 设置第二个元素
    condition.ISqlFormatterElem_addComponent getStrNameToken("x2")

    ' 2. 将这个条件对象包装为多行的 when 语句
    Set when = wrapToMultiWhenExpr(condition)
    g.ISqlFormatterElem_addComponent when

    ' 3. 设置嵌套深度
    g.ISqlFormatterElem_setElemNestCount 2, config

    ' 4. 检查条件对象的对齐长度
    ' and x1 <= x2
    ' 123456789
    ' 8 + 9 + 4(在 case 下的换行产生的前缀空格) + 4 (一个单位的空格)
    Debug.Assert condition.ISqlFormatterAlignmentElem_getAlignmentSize(config) = 25

End Sub

' 测试: setPrefixSpaceCount 方法
Private Sub test_ISqlFormatterElem_setPrefixSpaceCount()
    ' 这里使用一个条件对象作为函数体，并通过对齐长度来检查

    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim config As SqlFormatterConfiguration
    Set config = New SqlFormatterConfiguration

    Dim g As SqlFormatterCaseCol

    Dim condition As SqlFormatterTwoElemCondition

    Dim when As ISqlFormatterElem

    ' ==============================
    ' 1. 测试: 增加一个单行的条件元素
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 1. 创建一个条件对象
    Set condition = New SqlFormatterTwoElemCondition
    ' 设置 and
    condition.ISqlFormatterCondition_setLogicOperator getAndToken
    ' 设置第一个元素
    condition.ISqlFormatterElem_addComponent getStrNameToken("x1")
    ' 设置条件运算符 <=
    condition.ISqlFormatterCondition_setConditionOperator getLeConditionOperator
    ' 设置第二个元素
    condition.ISqlFormatterElem_addComponent getStrNameToken("x2")

    ' 2. 添加这个条件对象
    Set when = wrapToWhenExpr(condition)
    g.ISqlFormatterElem_addComponent when

    ' 3. 设置前缀空格数量
    g.ISqlFormatterElem_setPrefixSpaceCount 10, config

    ' 4. 检查条件对象的对齐长度
    ' and x1 <= x2
    ' 123456789
    ' 10 + 9 + 4(在 case 下的换行产生的前缀空格) + 5(when/else 字符长度 + 1 个分隔元素的空格)
    Debug.Assert condition.ISqlFormatterAlignmentElem_getAlignmentSize(config) = 28

    ' ==============================
    ' 2. 测试: 增加一个单行条件 + 多行元素
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 1. 创建一个条件对象
    Set condition = New SqlFormatterTwoElemCondition
    ' 设置 and
    condition.ISqlFormatterCondition_setLogicOperator getAndToken
    ' 设置第一个元素
    condition.ISqlFormatterElem_addComponent getStrNameToken("x1")
    ' 设置条件运算符 <=
    condition.ISqlFormatterCondition_setConditionOperator getLeConditionOperator
    ' 设置第二个元素
    condition.ISqlFormatterElem_addComponent getStrNameToken("x2")

    ' 2. 将这个条件对象包装为多行的 when 语句
    Set when = wrapToMultiWhenExpr(condition)
    g.ISqlFormatterElem_addComponent when

    ' 3. 设置前缀空格数量
    g.ISqlFormatterElem_setPrefixSpaceCount 10, config

    ' 4. 检查条件对象的对齐长度
    ' and x1 <= x2
    ' 123456789
    ' 10 + 9 + 4(在 case 下的换行产生的前缀空格) + 4 (一个单位的空格)
    Debug.Assert condition.ISqlFormatterAlignmentElem_getAlignmentSize(config) = 27
End Sub

' 测试: hasBoundaryParenthesis 方法
Private Sub test_ISqlFormatterElem_hasBoundaryParenthesis()
    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim g As SqlFormatterCaseCol

    ' ==============================
    ' 1. 添加左右括号
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 2. 增加左边界括号
    g.ISqlFormatterElem_addBoundaryLeftParenthesis
    Debug.Assert g.ISqlFormatterElem_hasBoundaryParenthesis = True

    ' 3. 增加右边界括号
    g.ISqlFormatterElem_addBoundaryRightParenthesis
    Debug.Assert g.ISqlFormatterElem_hasBoundaryParenthesis = True

    ' ==============================
    ' 2. 只添加右括号
    ' ==============================
    ' 重新创建对象，并只添加右边界括号
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    g.ISqlFormatterElem_addComponent getTableNameToken
    Debug.Assert g.ISqlFormatterElem_hasBoundaryParenthesis = False

    '    增加右边界括号
    g.ISqlFormatterElem_addBoundaryRightParenthesis
    Debug.Assert g.ISqlFormatterElem_hasBoundaryParenthesis = True
End Sub

' 测试: addBoundaryLeftParenthesis 方法
Private Sub test_ISqlFormatterElem_addBoundaryLeftParenthesis()
    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim g As SqlFormatterCaseCol
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    Dim elem As ISqlFormatterElem
    Set elem = g

    Dim config As SqlFormatterConfiguration
    Set config = New SqlFormatterConfiguration

    Dim strArr As IPrimitiveArrayRef

    Dim prefixSpace As String
    prefixSpace = "    "
    ' ==============================
    ' 2. 添加一个元素
    ' ==============================
    elem.addComponent getTableNameToken
    Set strArr = elem.toStringArray(config)
    Debug.Assert strArr.Count = 2
    Debug.Assert strArr.Item(0) = "case"
    Debug.Assert strArr.Item(1) = prefixSpace & TEST_TABLE_NAME

    ' ==============================
    ' 3. 添加一个左括号
    ' ==============================
    elem.addBoundaryLeftParenthesis

    Set strArr = elem.toStringArray(config)
    Debug.Assert strArr.Count = 3
    Debug.Assert strArr.Item(0) = "("
    Debug.Assert strArr.Item(1) = prefixSpace & "case"
    Debug.Assert strArr.Item(2) = prefixSpace & prefixSpace & TEST_TABLE_NAME

    ' ==============================
    ' 4. 添加多个左括号
    ' ==============================
    elem.addBoundaryLeftParenthesis(3)
    Set strArr = elem.toStringArray(config)
    Debug.Assert strArr.Count = 3
    Debug.Assert strArr.Item(0) = "(((("
    Debug.Assert strArr.Item(1) = prefixSpace & "case"
    Debug.Assert strArr.Item(2) = prefixSpace & prefixSpace & TEST_TABLE_NAME
End Sub

' 测试: addBoundaryRightParenthesis 方法
Private Sub test_ISqlFormatterElem_addBoundaryRightParenthesis()
    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim g As SqlFormatterCaseCol
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    Dim elem As ISqlFormatterElem
    Set elem = g

    Dim config As SqlFormatterConfiguration
    Set config = New SqlFormatterConfiguration

    Dim strArr As IPrimitiveArrayRef

    Dim prefixSpace As String
    prefixSpace = "    "

    ' ==============================
    ' 2. 添加一个元素
    ' ==============================
    elem.addComponent getTableNameToken
    Set strArr = elem.toStringArray(config)
    Debug.Assert strArr.Count = 2
    Debug.Assert strArr.Item(0) = "case"
    Debug.Assert strArr.Item(1) = prefixSpace & TEST_TABLE_NAME

    ' ==============================
    ' 3. 添加一个右括号
    ' ==============================
    elem.addBoundaryRightParenthesis

    Set strArr = elem.toStringArray(config)
    Debug.Assert strArr.Count = 3
    Debug.Assert strArr.Item(0) = prefixSpace & "case"
    Debug.Assert strArr.Item(1) = prefixSpace & prefixSpace & TEST_TABLE_NAME
    Debug.Assert strArr.Item(2) = ")"

    ' ==============================
    ' 4. 添加多个右括号
    ' ==============================
    elem.addBoundaryRightParenthesis(3)

    Set strArr = elem.toStringArray(config)
    Debug.Assert strArr.Count = 3
    Debug.Assert strArr.Item(0) = prefixSpace & "case"
    Debug.Assert strArr.Item(1) = prefixSpace & prefixSpace & TEST_TABLE_NAME
    Debug.Assert strArr.Item(2) = "))))"
End Sub

' 测试: getType 方法
Private Sub test_ISqlFormatterElem_getType()
    Dim g As SqlFormatterCaseCol
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 默认为 case
    Debug.Assert g.ISqlFormatterElem_getType = SqlTokenType.KEY_CASE
End Sub

' 测试: isComment 方法
Private Sub test_ISqlFormatterElem_isComment()
    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim g As SqlFormatterCaseCol
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    Dim elem As ISqlFormatterElem
    Set elem = g
    ' ==============================
    ' 2. 默认为 false
    ' ==============================
    Debug.Assert elem.isComment = False

    ' ==============================
    ' 3. 即使添加一个注释，也是 false
    ' ==============================
    elem.addComponent getShareLineCommentToken
    Debug.Assert elem.isComment = False

    elem.addComponent getSingleLineCommentToken
    Debug.Assert elem.isComment = False
End Sub

' 测试: isShareLineComment 方法
Private Sub test_ISqlFormatterElem_isShareLineComment()
    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim g As SqlFormatterCaseCol
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    Dim elem As ISqlFormatterElem
    Set elem = g

    ' ==============================
    ' 2. 默认为 false
    ' ==============================
    Debug.Assert elem.isShareLineComment = False

    ' ==============================
    ' 3. 即使添加一个注释，也是 false
    ' ==============================
    elem.addComponent getShareLineCommentToken
    Debug.Assert elem.isShareLineComment = False

    elem.addComponent getSingleLineCommentToken
    Debug.Assert elem.isShareLineComment = False
End Sub

' 测试: isSingleLineComment 方法
Private Sub test_ISqlFormatterElem_isSingleLineComment()
    ' ==============================
    ' 1. 初始化
    ' ==============================
    Dim g As SqlFormatterCaseCol
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    Dim elem As ISqlFormatterElem
    Set elem = g

    ' ==============================
    ' 2. 默认为 false
    ' ==============================
    Debug.Assert elem.isShareLineComment = False

    ' ==============================
    ' 3. 即使添加一个注释，也是 false
    ' ==============================
    elem.addComponent getShareLineCommentToken
    Debug.Assert elem.isSingleLineComment = False

    elem.addComponent getSingleLineCommentToken
    Debug.Assert elem.isSingleLineComment = False
End Sub

' 测试: isEndsWithComment 方法
Private Sub test_ISqlFormatterElem_isEndsWithComment()
    ' 参考: test_ISqlFormatterElem_addComponent
End Sub

' 测试: isMultiLine 方法
Private Sub test_ISqlFormatterElem_isMultiLine()
    ' 参考: test_ISqlFormatterElem_addComponent
End Sub

' 测试: toString + toStringArray 方法
Private Sub test_ISqlFormatterElem_toString_toStringArray()
    Dim config As SqlFormatterConfiguration
    Set config = New SqlFormatterConfiguration

    Dim strArr As IPrimitiveArrayRef

    Dim g As SqlFormatterCaseCol

    Dim prefixSpace As String
    prefixSpace = "    "

    ' 1. 只有一个 case
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 1
    Debug.Assert strArr.Item(0) = "case"

    ' 2. 设置边界括号: 左边界括号
    g.ISqlFormatterElem_addBoundaryLeftParenthesis(2)
    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 1
    Debug.Assert strArr.Item(0) = "((case"

    ' 3. 设置边界括号: 左 + 右边界括号
    g.ISqlFormatterElem_addBoundaryRightParenthesis(2)
    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 1
    Debug.Assert strArr.Item(0) = "((case))"

    ' 4. 添加一个和前一个元素同一行的注释
    g.ISqlFormatterElem_addComponent getShareLineCommentToken
    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 3
    Debug.Assert strArr.Item(0) = "(("
    Debug.Assert strArr.Item(1) = "    case --aaaaaa"
    Debug.Assert strArr.Item(2) = "))"

    ' 5. 添加一个单行的元素
    g.ISqlFormatterElem_addComponent getStrNameToken("x1")

    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 4
    Debug.Assert strArr.Item(0) = "(("
    Debug.Assert strArr.Item(1) = "    case --aaaaaa"
    Debug.Assert strArr.Item(2) = "        x1"
    Debug.Assert strArr.Item(3) = "))"

    ' 6. 添加一个和前一个元素同一行的注释
    g.ISqlFormatterElem_addComponent getShareLineCommentToken

    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 4
    Debug.Assert strArr.Item(0) = "(("
    Debug.Assert strArr.Item(1) = "    case --aaaaaa"
    Debug.Assert strArr.Item(2) = "        x1 --aaaaaa"
    Debug.Assert strArr.Item(3) = "))"

    ' ==============================
    ' 3. 只有右括号
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 2. 设置边界括号: 右边界括号
    g.ISqlFormatterElem_addBoundaryRightParenthesis(2)
    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 1
    Debug.Assert strArr.Item(0) = "case))"

    ' 3. 增加一个单行元素
    g.ISqlFormatterElem_addComponent getStrNameToken("x1")
    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 3
    Debug.Assert strArr.Item(0) = "    case"
    Debug.Assert strArr.Item(1) = "        x1"
    Debug.Assert strArr.Item(2) = "))"

    ' ==============================
    ' 3. 检查一个 case 关键字 + 一个同行注释
    ' ==============================
    Set g = New SqlFormatterCaseCol
    g.Init getCaseToken

    ' 添加一个同行注释
    g.ISqlFormatterElem_addComponent getShareLineCommentToken

    Set strArr = g.ISqlFormatterElem_toStringArray(config)
    Debug.Assert strArr.Count = 1
    Debug.Assert strArr.Item(0) = "case --aaaaaa"
End Sub